// logger.cpp
#include "log.h"
#include <memory>
#include <iostream>
#include "../config/configmanager.h"
#include <json.h>
#include <value.h>


std::shared_ptr<Logger> Logger::mInstance= nullptr;
std::once_flag Logger::mflag;


Logger::Logger():m_bInit(false),m_level("debug"), m_path(""),
                 m_size(50*1024*1024),m_count(10),
                 m_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] [thread %t] [%s %!:%#] %v") {
}
Logger::~Logger(){
    if(m_bInit){
        UnInit();
    }
}
//当使用std::call_once时，需要使用std::shared_ptr的自定义删除器来释放单例实例。
//这可以通过传递一个lambda函数作为std::shared_ptr的第二个参数来实现。
/*
 * std::shared_ptr将使用自定义的删除器来释放单例实例。现在，应该能够成功编译并运行你的代码。对于高并发情况下的唯一性，
 * std::call_once将确保只有一个线程能够创建单例实例，并安全地共享该实例。
*/
std::shared_ptr<Logger> Logger::GetInstance() {
    std::call_once(mflag, []() {
        mInstance = std::shared_ptr<Logger>(new Logger(),
                                            [](Logger* ptr){delete ptr;});
    });

    return mInstance;
}


void Logger::Init() {
    if(m_bInit){
        printf("It's already initialized\n");
    }else {
        std::shared_ptr<CConfigManager> pCfgManger = CConfigManager::GetInstance();
        if(pCfgManger!= nullptr){
            std::string stdPath = "./CFG/spdlogcfg";//AppConfig::SPDLOGJsonPath.toStdString();
            std::cout << "stdPath: " << stdPath << std::endl;
            Json::Value tmpValue = Json::Value::null;
            if(!pCfgManger->loadConfig(stdPath, tmpValue)){
                return ;
            }
            if (tmpValue.isMember("level") && tmpValue["level"].isString()){
                m_level = tmpValue["level"].asString().c_str();
            }
            if (tmpValue.isMember("path") && tmpValue["path"].isString()){
                m_path = tmpValue["path"].asString().c_str();
            }
            if (tmpValue.isMember("size") && tmpValue["size"].isInt64()){
                m_size = tmpValue["size"].asInt64() * 1024*1024*1024;
            }
            if (tmpValue.isMember("count") && tmpValue["count"].isInt64()){
                m_count = tmpValue["count"].asInt64();
            }
            if (tmpValue.isMember("pattern") && tmpValue["pattern"].isString()){
                m_pattern = tmpValue["pattern"].asString().c_str();
            }
        }
        try{
            //自定义的sink，日志的名字是file_logger
            m_bInit = true;
            auto consoleSink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();

            consoleSink->set_level(spdlog::level::from_str(m_level));

            auto fileSink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(m_path, m_size, m_count);
            fileSink->set_level(spdlog::level::trace);
            fileSink->set_pattern(m_pattern);
            //    //[%Y-%m-%d %H:%M:%S.%e] 时间
            //    //[%l] 日志级别
            //    //[%t] 线程
            //    //[%s] 文件
            //    //[%#] 行号
            //    //[%!] 函数
            //    //[%v] 实际文本
            //    loggerPtr->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] [thread %t] [%s %!:%#] %v");

            /*Sink  组合*/
            std::vector<spdlog::sink_ptr> sinks;
            sinks.push_back(consoleSink);
            sinks.push_back(fileSink);

            loggerPtr =  std::make_shared<spdlog::logger>(" ", begin(sinks), end(sinks));
            spdlog::register_logger(loggerPtr);
            loggerPtr->flush_on(spdlog::level::err);
            spdlog::flush_every(std::chrono::seconds(2));
            printf(" Spdlog create success");
        }catch(const spdlog::spdlog_ex& ex){
            printf("Splog init error {%s}", ex.what());
        }
    }
}
/*
 * trace 0
 * debug 1
 * info 2
 * warn 3
 * error 4
 * critical 5
 * off 6 (not use)
 */
std::string Logger::GetLogLevel() {
    auto level = loggerPtr->level();
    return spdlog::level::to_string_view(level).data();
}

void Logger::SetLogLevel(const std::string& log_level) {
    auto level = spdlog::level::from_str(log_level);
    if (level == spdlog::level::off) {
        LOG_WARN("Given invalid log level {}", log_level);
    } else {
        loggerPtr->set_level(level);
        loggerPtr->flush_on(level);
        //定时flush到文件，每三秒刷新一次
        spdlog::flush_every(std::chrono::seconds(1));
        spdlog::register_logger(loggerPtr);
    }
}

void Logger::UnInit(){

    if(m_bInit) {
        loggerPtr->flush();
        spdlog::drop_all();
        spdlog::shutdown();
        m_bInit = false;
    }
}
